package com.example.blog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.example.blog.base.CurrentAccount;
import com.example.blog.common.StatusEnums;
import com.example.blog.entity.Article;
import com.example.blog.entity.Follow;
import com.example.blog.entity.Like;
import com.example.blog.entity.SysUser;
import com.example.blog.entity.vo.favorites.FavoritesDetailInfoVO;
import com.example.blog.entity.vo.like.LikeDetailInfoVO;
import com.example.blog.mapper.LikeMapper;
import com.example.blog.service.ArticleService;
import com.example.blog.service.LikeService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.blog.service.SysUserService;
import com.example.blog.util.BeanUtils;
import com.example.blog.util.CurrentUserUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 点赞表 服务实现类
 * </p>
 *
 * @author wlh
 * @since 2024-01-10
 */
@Service
public class LikeServiceImpl extends ServiceImpl<LikeMapper, Like> implements LikeService {

    @Autowired
    private ArticleService articleService;

    @Autowired
    @Lazy
    private SysUserService sysUserService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(Long articleId) {

        Article article = articleService.getByIdNotNull(articleId);
        Like like = new Like();

        like.setIsRead(StatusEnums.NOT_READ.getValue());
        like.setArticleId(articleId);
        like.setUserId(article.getCreatedBy());
        save(like);

        articleService.incrementLike(article, 1);
    }

    @Override
    public void del(Long articleId) {

        Article article = articleService.getByIdNotNull(articleId);
        CurrentAccount currentUser = CurrentUserUtils.currentUser();

        LambdaUpdateWrapper<Like> updateWrapper = new LambdaUpdateWrapper<>();

        updateWrapper.eq(Like::getArticleId, articleId)
                .eq(Like::getCreatedBy, currentUser.getId())
        ;

        remove(updateWrapper);

        articleService.incrementLike(article, -1);
    }

    @Override
    public Long getNewCountByUser(Long userId) {
        LambdaQueryWrapper<Like> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Like::getUserId, userId)
                .eq(Like::getIsRead, StatusEnums.NOT_READ.getValue());
        return count(queryWrapper);
    }

    @Override
    public List<LikeDetailInfoVO> newLike() {

        LambdaQueryWrapper<Like> queryWrapper = new LambdaQueryWrapper<>();

        CurrentAccount user = CurrentUserUtils.currentUser();

        queryWrapper.eq(Like::getUserId, user.getId())
                .orderByAsc(Like::getIsRead)
                .orderByDesc(Like::getCreatedTime)
        ;

        List<Like> list = list(queryWrapper);
        if (list.isEmpty()) {
            return new ArrayList<>();
        }
        Set<Long> uids = new HashSet<>();
        Set<Long> artIds = new HashSet<>();

        list.forEach(like -> {
            uids.add(like.getCreatedBy());
            artIds.add(like.getArticleId());
        });

        Map<Long, Article> articleMap = articleService.listByIds(artIds)
                .stream()
                .collect(Collectors.toMap(Article::getId, Function.identity()));

        Map<Object, SysUser> sysUserMap = sysUserService.listByIds(uids)
                .stream()
                .collect(Collectors.toMap(SysUser::getId, Function.identity()));

        return list.stream()
                .map(like -> {
                    LikeDetailInfoVO likeDetailInfoVO = BeanUtils.copyProperties(like, LikeDetailInfoVO.class);
                    SysUser sysUser = sysUserMap.get(likeDetailInfoVO.getCreatedBy());
                    if (sysUser != null) {
                        BeanUtils.copyProperties(sysUser, likeDetailInfoVO, false);
                    }

                    Article article = articleMap.get(likeDetailInfoVO.getArticleId());
                    if (article != null) {
                        likeDetailInfoVO.setSummary(article.getSummary());
                        likeDetailInfoVO.setArticleTitle(article.getTitle());
                    }
                    return likeDetailInfoVO;
                })
                .toList();
    }

    @Override
    public void read() {

        CurrentAccount user = CurrentUserUtils.currentUser();
        LambdaUpdateWrapper<Like> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Like::getUserId, user.getId())
                .eq(Like::getIsRead, StatusEnums.NOT_READ.getValue())
                .set(Like::getIsRead, StatusEnums.READ.getValue());

        update(updateWrapper);

    }

    @Override
    public Long getByUserAndArticle(Long userId, Long articleId) {

        LambdaQueryWrapper<Like> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Like::getCreatedBy, userId)
                .eq(Like::getArticleId, articleId);
        return count(queryWrapper);
    }
}
